package ru.vt.simpleservlet;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import ru.vt.simpleservlet.data.DataPosition;
import ru.vt.simpleservlet.dbinterraction.Extractor;
import ru.vt.simpleservlet.dbinterraction.Inserter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.channels.FileChannel;

import static org.imgscalr.Scalr.resize;

public class UploaderBean {
    /**
     * Переменная для передаваямого от клиента файла
     */
    private UploadedFile uploadedFile = null;
    /**
     * Показывает факт успешной передачи файла на сервер
     */
    private Boolean uploaded = false;
    /**
     * Название сформированного изображения
     */
    private String smallImageName = "";
    /**
     * Уникальный идентификатор, получаемый из хэш кода
     */
    private String localVersionCode = "";
    /**
     * Название элемента
     */
    private String localElementName = "";
    /**
     * Название категории
     */
    private String localCategoryName;
    /**
     * Содержание элемента
     */
    private String localTextContent;
    /**
     * Цена элемента
     */
    private String localPrice;

    /**
     * Загрузка файла на сервер
     */
    public void uploadFile() {
        String prefix = FilenameUtils.getBaseName(uploadedFile.getName());
        String suffix = FilenameUtils.getExtension(uploadedFile.getName());
        File file = null;
        OutputStream output = null;
        try {
            file = File.createTempFile(prefix + "__", "." + suffix, new File(Extractor.getImageTmpFolder()));
            output = new FileOutputStream(file);
            IOUtils.copy(uploadedFile.getInputStream(), output);
            File smallImageFile = simpleConvertImage(file, 200);
            if (!smallImageFile.equals(null)) {
                smallImageName = smallImageFile.getName();
                localVersionCode = Integer.toString(Math.abs(smallImageName.hashCode()));
                uploaded = true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(output);
            if (file != null) file.delete();
        }
    }

    /**
     * Проверяет входные параметры и сохраняет значения в БД
     */
    public void saveElementInBD() {
        //Проверка всех входных строк на null и пустотность
        if (validateString(localCategoryName) && validateString(localElementName) && validateString(localPrice) && validateString(localTextContent) && validateString(localVersionCode)) {
            File smalIFile = new File(Extractor.getImageTmpFolder() + smallImageName);
            //Проверка на существование файла с конвертированным изображением
            if (smalIFile.exists()) {
                copyFile(smalIFile.getAbsolutePath(), Extractor.getImageFolder() + smalIFile.getName());
                smalIFile.delete();
                Float price = Float.parseFloat(localPrice);
                DataPosition dataPosition = new DataPosition(localVersionCode, localCategoryName, localElementName, localTextContent, price, smallImageName);
                Inserter.addData(dataPosition);
            }
        }
        eraseAll();
    }

    /**
     * Стирает переменные бина, удаляет файл, если был создан и выставляет uploaded=false
     */
    public void eraseAll() {
        this.uploadedFile = null;
        this.uploaded = false;
        localCategoryName = "";
        localElementName = "";
        localPrice = "";
        localTextContent = "";
        localVersionCode = "";
        File smalIFile = new File(Extractor.getImageTmpFolder() + smallImageName);
        if (!smalIFile.equals(null)) {
            smalIFile.delete();
            smallImageName = "";
        }
    }

    /**
     * Метод конвертирует изображение в указанные размеры и возвращает получившееся в формате "png"
     *
     * @param file      Файл с изображением
     * @param imageSize Размер изображения
     * @return Сконвертируемое изображение
     */
    private static File simpleConvertImage(File file, int imageSize) {
        String justName = file.getName().replaceAll(".jpeg", "").replaceAll(".jpg", "").replaceAll(".png", "").replaceAll(".gif", "");
        File convertedFile = null;
        try {
            BufferedImage image = ImageIO.read(file);
            convertedFile = new File(file.getParent() + File.separator + justName + "_.png");
            ImageIO.write(createThumbnail(image, imageSize), "png", convertedFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return convertedFile;
    }

    /**
     * Проверка строки на пустотность и null
     *
     * @param s Трока для проверки
     * @return true если проверка пройден, false если нет
     */
    private static Boolean validateString(String s) {
        if ((s.equals(null)) && (s.equals(""))) {
            return false;
        }
        return true;
    }

    /**
     * Метод возвращает стрим измененного по размерности изображения
     *
     * @param bufferedImage Стрим с изначальным изображением
     * @param imageSize     Параметр конечной размерности изображения в пикселях
     * @return Стрим с измененным изображением
     */
    private static BufferedImage createThumbnail(BufferedImage bufferedImage,
                                                 int imageSize) {
        bufferedImage = resize(bufferedImage, imageSize);
        return bufferedImage;
    }

    public static void copyFile(String p_srcFileName, String p_dstFileName) {
        try {
            FileChannel srcChannel = new FileInputStream(p_srcFileName).getChannel();
            FileChannel dstChannel = new FileOutputStream(p_dstFileName).getChannel();
            dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
            srcChannel.close();
            dstChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public UploadedFile getUploadedFile() {
        return uploadedFile;
    }

    public void setUploadedFile(UploadedFile uploadedFile) {
        this.uploadedFile = uploadedFile;
    }

    public Boolean getUploaded() {
        return uploaded;
    }

    public void setUploaded(Boolean uploaded) {
        this.uploaded = uploaded;
    }

    public String getSmallImageName() {
        return smallImageName;
    }

    public void setSmallImageName(String smallImageName) {
        this.smallImageName = smallImageName;
    }

    public String getLocalVersionCode() {
        return localVersionCode;
    }

    public void setLocalVersionCode(String localVersionCode) {
        this.localVersionCode = localVersionCode;
    }

    public String getLocalElementName() {
        return localElementName;
    }

    public void setLocalElementName(String localElementName) {
        this.localElementName = localElementName;
    }

    public String getLocalCategoryName() {
        return localCategoryName;
    }

    public void setLocalCategoryName(String localCategoryName) {
        this.localCategoryName = localCategoryName;
    }

    public String getLocalTextContent() {
        return localTextContent;
    }

    public void setLocalTextContent(String localTextContent) {
        this.localTextContent = localTextContent;
    }

    public String getLocalPrice() {
        return localPrice;
    }

    public void setLocalPrice(String localPrice) {
        this.localPrice = localPrice;
    }
}
